POST /short-link/internal - 内部短链接创建接口

接口功能说明

该接口用于内部服务间通信,将任意长URL转换为短链接(s.pear.us 域名)。主要用于字符限制场景,如短信模板、邮件模板、营销推广链接等。

[!info] 与 /short-link/create 的区别 | 特性 | /short-link/internal | /short-link/create | |------|------------------------|----------------------| | 认证方式 | JWT Token (BUSINESS_PARTNER) | AdminGuard (管理员权限) | | 使用场景 | 服务间调用、业务系统集成 | 管理后台手动创建 | | 权限要求 | 需要 JWT Token | 需要管理员权限 |


请求地址 & 请求方式

POST /short-link/internal

环境示例:

  • Release: https://release.katana-api.1m.app/short-link/internal
  • Development: http://localhost:4000/short-link/internal

请求头 (Headers)

Header 必填 类型 说明
Authorization string JWT Token,格式:Bearer <token>
Content-Type string 必须为 application/json
from string 来源标识,如 client
x-track-id string 追踪ID,用于请求链路追踪

请求参数 (Body)

请求体结构

字段 必填 类型 说明 示例
originalUrl string 需要缩短的原始URL(完整URL) https://release.pear.us/neo/post/000011?aff=ehf843
ttlDays number 短链接有效期(天数),不传则永久有效 30

TypeScript 类型定义

export interface CreateGenericShortLinkRequest {
  originalUrl: string;  // 必填:原始URL
  ttlDays?: number;     // 可选:有效期(天数)
}

请求示例

{
  "originalUrl": "https://release.pear.us/neo/post/000011?aff=ehf843"
}

带有效期的请求:

{
  "originalUrl": "https://release.pear.us/neo/post/000011?aff=ehf843",
  "ttlDays": 30
}

响应结构 & 字段说明

成功响应

HTTP Status Code: 200 OK

export interface CreateShortLinkResponse {
  shortUrl: string;      // 短链接完整地址
  code: string;          // 短链接码(短链接的最后部分)
  originalUrl: string;   // 原始URL
  createdAt: string;     // 创建时间(ISO 8601格式)
  expiresAt?: string;    // 过期时间(ISO 8601格式,如有设置ttlDays)
}
字段 类型 说明
shortUrl string 短链接完整地址,格式:https://s.pear.us/{code}
code string 短链接码,用于手动构建短链接
originalUrl string 原始URL(与请求参数一致)
createdAt string 短链接创建时间,ISO 8601格式
expiresAt string 过期时间,仅在设置 ttlDays 时返回

成功示例

Request:

curl -X POST 'https://release.katana-api.1m.app/short-link/internal' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' \
  -H 'Content-Type: application/json' \
  -d '{
    "originalUrl": "https://release.pear.us/neo/post/000011?aff=ehf843"
  }'

Response:

{
  "shortUrl": "https://s.pear.us/abc123xyz",
  "code": "abc123xyz",
  "originalUrl": "https://release.pear.us/neo/post/000011?aff=ehf843",
  "createdAt": "2026-02-27T09:30:00.000Z"
}

带有效期的响应示例:

{
  "shortUrl": "https://s.pear.us/abc123xyz",
  "code": "abc123xyz",
  "originalUrl": "https://release.pear.us/neo/post/000011?aff=ehf843",
  "createdAt": "2026-02-27T09:30:00.000Z",
  "expiresAt": "2026-03-29T09:30:00.000Z"
}

异常场景 & 错误响应

错误响应格式

export interface ShortLinkApiResponse<T = unknown> {
  success: boolean;    // false 表示失败
  error?: string;      // 错误信息
  statusCode: number;  // HTTP状态码
}

错误场景列表

HTTP状态码 错误场景 错误信息示例
401 JWT Token 无效或过期 Unauthorized
400 请求参数缺失 originalUrl is required
500 短链接服务配置错误 SHORT_LINK_API_URL environment variable is required
500 短链接API调用失败 Failed to create short link: ...
500 请求超时 timeout of 10000ms exceeded

错误示例

1. 认证失败 (401)

{
  "statusCode": 401,
  "message": "Unauthorized"
}

2. 环境变量未配置 (500)

{
  "statusCode": 500,
  "message": "SHORT_LINK_API_URL environment variable is required"
}

3. 短链接API错误 (500)

{
  "statusCode": 500,
  "message": "Failed to create short link: Invalid URL format"
}

业务逻辑详解

处理流程

sequenceDiagram
    participant Client as 客户端
    participant Controller as ShortLinkController
    participant Service as ShortLinkService
    participant ExternalAPI as 短链接外部API

    Client->>Controller: POST /short-link/internal
    Note over Client,Controller: Authorization: Bearer <JWT>

    Controller->>Service: createShortLink(originalUrl, ttlDays)
    Note over Service: 验证环境变量

    Service->>ExternalAPI: POST /create
    Note over Service,ExternalAPI: 10秒超时

    ExternalAPI-->>Service: CreateShortLinkResponse
    Note over Service: 验证响应成功

    Service-->>Controller: CreateShortLinkResponse
    Controller-->>Client: 200 OK + 短链接数据

环境依赖

环境变量 必填 说明
SHORT_LINK_API_URL 短链接服务API地址
SHORT_LINK_API_KEY 短链接服务API密钥

超时设置

  • API调用超时: 10000ms (10秒)
  • 超时后抛出异常并返回错误响应

认证逻辑

该接口受全局 JwtAuthGuard 保护:

  1. 请求头必须包含有效的 JWT Token
  2. Token中必须包含有效的用户信息
  3. Token过期后返回 401 Unauthorized

数据库操作说明

[!important] 数据库操作隔离 该接口在 katana-server 中不涉及任何数据库操作,所有数据存储由独立的短链接服务负责。

katana-server 侧:无数据库操作

客户端 → ShortLinkController → ShortLinkService → 外部短链接API
                                                    ↓
                                            (s.pear.us 服务数据库)

本接口在 katana-server 中仅作为 HTTP 代理

// short-link.service.ts 核心逻辑
async createShortLink(url: string, ttlDays?: number) {
  // 1. 从配置读取环境变量(无数据库查询)
  const apiUrl = this.configService.get<string>('SHORT_LINK_API_URL');
  const apiKey = this.configService.get<string>('SHORT_LINK_API_KEY');

  // 2. 直接调用外部API(无数据库写入)
  const response = await axios.post(`${apiUrl}/create`, request, {
    headers: { Authorization: `Bearer ${apiKey}` },
    timeout: 10000,
  });

  // 3. 返回外部API的响应
  return response.data.data;
}

外部短链接服务:负责数据库操作

独立的短链接服务(s.pear.us)负责以下数据库操作:

操作 说明 数据表(推测)
写入 存储短链接码 → 原始URL 的映射关系 short_links
读取 用户访问短链接时查询原始URL并重定向 short_links
清理 过期短链接的定期清理(如实现了TTL机制) 定时任务

架构设计优势

graph LR
    A[katana-server] -- HTTP代理 --> B[s.pear.us 短链接服务]
    B -- 存储/查询 --> C[(短链接数据库)]
    A -.无直接操作.-> C

    style A fill:#e3f2fd
    style B fill:#fff9c4
    style C fill:#f3e5f5

[!tip] 服务分离设计的优势

  • 解耦: 短链接逻辑独立,不影响主业务数据库
  • 复用: 其他服务可直接调用短链接服务,无需重复实现
  • 维护: 短链接算法升级/扩容只需修改外部服务
  • 性能: 短链接高并发访问不影响主业务系统
  • 独立部署: 可根据短链接访问量独立扩缩容

注意事项

[!warning] URL 格式要求

  • originalUrl 必须是完整的、有效的 URL
  • 必须包含协议(http://https://
  • URL中的特殊字符无需手动编码,服务会自动处理

[!warning] 短链接唯一性

  • 同一个 originalUrl 多次调用可能生成不同的短链接
  • 如需复用已有短链接,请在调用端实现缓存逻辑

[!warning] 有效期计算

  • ttlDays 参数表示从创建之日起的有效天数
  • 不传该参数则短链接永久有效
  • 过期后短链接将无法访问

[!tip] 建议使用场景

  • ✅ 短信营销链接
  • ✅ 邮件模板中的商品链接
  • ✅ 社交媒体推广链接
  • ✅ 带追踪参数的联盟链接(如 ?aff=xxx
  • ✅ 二维码生成(短链接生成更简单的二维码)

[!danger] 安全注意

  • 不要将敏感信息(如密码、Token)放在短链接中
  • 短链接可被推算,不适合作为私密访问入口
  • 建议为敏感内容设置较短的有效期

代码位置

文件 路径
Controller src/short-link/short-link.controller.ts:66-72
Service src/short-link/short-link.service.ts:26-75
DTO src/short-link/dto/short-link.dto.ts:6-9

相关接口

  • [[POST /short-link/create]] - 管理员创建短链接
  • [[POST /short-link/verification]] - 创建验证链接

results matching ""

    No results matching ""